{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. _nb_constraints_penalty:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "%%capture\n",
    "%run ./index.ipynb"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Constraint Violation (CV) as Penalty"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another well-known way of handling constraints is removing the constraint and adding it as a penalty to objective(s). One easy way of achieving that is redefining the problem, as shown below using the `ConstraintsAsPenalty` class. Nevertheless, whenever two numbers are added, normalization can become an issue. Thus, commonly a penalty coefficient (here `penalty`) needs to be defined. It can be helpful to play with this parameter if the results are not satisfying."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from pymoo.algorithms.soo.nonconvex.de import DE\n",
    "from pymoo.constraints.as_penalty import ConstraintsAsPenalty\n",
    "from pymoo.optimize import minimize\n",
    "from pymoo.core.evaluator import Evaluator\n",
    "from pymoo.core.individual import Individual\n",
    "\n",
    "problem = ConstrainedProblem()\n",
    "\n",
    "algorithm = DE()\n",
    "\n",
    "res = minimize(ConstraintsAsPenalty(problem, penalty=100.0),\n",
    "               algorithm,\n",
    "               seed=1,\n",
    "               verbose=False)\n",
    "\n",
    "res = Evaluator().eval(problem, Individual(X=res.X))\n",
    "\n",
    "print(\"Best solution found: \\nX = %s\\nF = %s\\nCV = %s\" % (res.X, res.F, res.CV))"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. _nb_constraints_no_feas_found:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Solution only almost feasible"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please note that this approach might not always find a feasible solution (because the algorithm does not know anything about whether a solution is feasible or not). For instance, see the example below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymoo.algorithms.soo.nonconvex.de import DE\n",
    "from pymoo.constraints.as_penalty import ConstraintsAsPenalty\n",
    "from pymoo.optimize import minimize\n",
    "from pymoo.core.evaluator import Evaluator\n",
    "from pymoo.core.individual import Individual\n",
    "\n",
    "res = minimize(ConstraintsAsPenalty(problem, penalty=2.0),\n",
    "               algorithm,\n",
    "               seed=1,\n",
    "               verbose=False)\n",
    "\n",
    "res = Evaluator().eval(problem, Individual(X=res.X))\n",
    "\n",
    "print(\"Best solution found: \\nX = %s\\nF = %s\\nCV = %s\" % (res.X, res.F, res.CV))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In such cases, it can be helpful to perform another search for the solution found to the original problem to find a feasible one. This second search method can, for instance, be realized by a local search or by using again a population-based method injecting the solution found before. Here, we demonstrate the latter:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymoo.operators.sampling.lhs import LHS\n",
    "\n",
    "sampling = LHS().do(problem, 100)\n",
    "sampling[0].X = res.X\n",
    "\n",
    "algorithm = DE(sampling=sampling)\n",
    "\n",
    "res = minimize(problem, algorithm)\n",
    "\n",
    "print(\"Best solution found: \\nX = %s\\nF = %s\\nCV = %s\" % (res.X, res.F, res.CV))"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
